#!/usr/bin/env python

"""
 This source file is part of the Swift.org open source project

 Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
 Licensed under Apache License v2.0 with Runtime Library Exception

 See http://swift.org/LICENSE.txt for license information
 See http://swift.org/CONTRIBUTORS.txt for Swift project authors

 -------------------------------------------------------------------------
 This script contains helper operations to use Docker for SwitPM development
 and testing.
"""

import argparse
import urllib2
import os
import subprocess
import yaml

script_dir = os.path.dirname(os.path.realpath(__file__))

def call(args):
    """Prints and executes a command."""
    print(" ".join(args))
    return subprocess.call(args)

def docker_run(command_args):
    """Runs a command in the container."""
    swiftpm_dir = os.path.normpath(os.path.join(script_dir, '../..'))
    llbuild_dir = os.path.normpath(os.path.join(swiftpm_dir, '../llbuild'))
    swift_driver_dir = os.path.normpath(os.path.join(swiftpm_dir, '../swift-driver'))
    yams_dir = os.path.normpath(os.path.join(swiftpm_dir, '../yams'))
    call([
        "docker",
        "run",
        "-it",
        "--security-opt", "seccomp=unconfined",
        "-v", "%s:/swiftpm" % swiftpm_dir,
        "-v", "%s:/llbuild" % llbuild_dir,
        "-v", "%s:/swift-driver" % swift_driver_dir,
        "-v", "%s:/yams" % yams_dir,
        "-w", "/swiftpm",
        "--rm",
        "swiftpm-docker-1804"
    ] + command_args)

def build(_):
    """Builds a docker image with the latest snapshot."""

    # Get latest snapshot info.
    latest_build_url = "https://swift.org/builds/development/ubuntu1804/latest-build.yml"
    latest_build_data = yaml.load(urllib2.urlopen(latest_build_url).read())
    snapshot_filename = latest_build_data["download"]
    # FIXME: We shouldn"t need to do this, it should be available in the API.
    snapshot_name = snapshot_filename.replace("-ubuntu18.04.tar.gz", "")
    base_url = latest_build_url.rsplit("/", 1)[0]
    latest_snapshot_url = base_url + "/" + snapshot_name + "/" + snapshot_filename

    # Download latest snapshot (if necessary).
    if snapshot_filename in os.listdir(script_dir):
        print("Not downloading: %s" % latest_snapshot_url)
    else:
        # FIXME: We should remove old tarballs if we have newer ones.
        result = call([
            "curl",
            "-o",
            os.path.join(script_dir, snapshot_filename),
            latest_snapshot_url
        ])

        if result != 0:
            print("Unable to install package: %s" % latest_snapshot_url)
            exit(1)

    # Create docker image.
    call([
        "docker",
        "build",
        "-t", "swiftpm-docker-1804",
        "--build-arg", "SNAPSHOT=%s" % snapshot_filename,
        script_dir
    ])

def run(args):
    """Runs an executable in the container."""
    docker_run([args.executable] + args.arguments)

def bootstrap(args):
    """Runs the bootstrap script in the container."""
    docker_run(["Utilities/bootstrap"] + args.arguments)

def build_run(args):
    """Runs a built swift executable in the container."""
    docker_run([".build/x86_64-unknown-linux-gnu/debug/swift-" + args.command] + args.arguments)

def main():
    """Main script entry-point."""

    parser = argparse.ArgumentParser(
        usage="%(prog)s [build|run|bootstrap|swift]",
        description="This script simplifies all the docker operations to build "
                    "and run a container for SwiftPM development and testing "
                    "on Linux.")
    subparsers = parser.add_subparsers(dest='command')

    # build
    parser_build = subparsers.add_parser(
        "build",
        help="builds a docker image from the latest snapshot.")
    parser_build.set_defaults(func=build)

    # run
    parser_run = subparsers.add_parser(
        "run",
        help="runs an executable in a container.")
    parser_run.add_argument("executable", help="the executable to run")
    parser_run.add_argument("arguments", nargs="*")
    parser_run.set_defaults(func=run)

    # bootstrap
    parser_bootstrap = subparsers.add_parser(
        "bootstrap",
        help="runs the bootstrap script in a container.")
    parser_bootstrap.add_argument("arguments", nargs="*")
    parser_bootstrap.set_defaults(func=bootstrap)

    # spm
    parser_swift_build = subparsers.add_parser(
        "swift",
        help="runs a SwiftPM executable in a container.")
    parser_swift_build.add_argument("arguments", nargs="*")
    parser_swift_build.set_defaults(func=build_run)

    args = parser.parse_args()
    args.func(args)

if __name__ == "__main__":
    main()
